/* Vecmath.

   Copyright (C) 2001, 2002, 2003 Stefan Maierhofer.

   Written by Stefan Maierhofer <sm@cg.tuwien.ac.at>

   This file is part of Vecmath.

   Vecmath is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   Vecmath is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Vecmath; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */

using System;
using NUnit.Framework;

namespace Vecmath.Shapes
{

    /// <summary>
    /// Sphere3D.
    /// </summary>
    public struct Sphere3D
    {

        public static Sphere3D UnitSphere = new Sphere3D(new Pnt3D(0,0,0), 1.0);

        public Sphere3D(Pnt3D center, double radius)
        {
            this.center = center;
            this.radius = radius;
        }

        public Pnt3D Center
        {
            get { return center; }
            set { center = value; }
        }

        public double Radius
        {
            get { return radius; }
            set { radius = value; }
        }

        public bool Intersect(Ray3D ray, ref double t, ref Vec3D normal)
        {
            Vec3D l = center - ray.Point;
            double s = Vec3D.Dot(l, ray.Direction);
            double l2 = l.SquaredLength;
            double rr = radius * radius;
            if (s < 0.0 && l2 > rr) return false;
            double m2 = l2 - s * s;
            if (m2 > rr) return false;
            double q = Math.Sqrt(rr - m2);
            if (l2 > rr) t = s - q;
            else t = s + q;
            normal = (ray.Point + ray.Direction * t) - center;
            normal.Normalize();
            return true;
        }

        private Pnt3D center;
        private double radius;

    }

}
